import {Component, OnDestroy, OnInit, ViewChild} from '@angular/core';
import {FormControl, FormGroup} from "@angular/forms";
import {BarnProduct} from "../../product/entity/barn-product";
import {ProductService} from "../../product/service/product.service";
import {Constants} from "../../../../../tools";
import {BarnSqlService} from "../service/barn-sql.service";
import {BarnSql} from "../entity/barn-sql";
import {Clipboard} from "@angular/cdk/clipboard";
import {NzMessageService} from "ng-zorro-antd/message";
import {Subject, Subscription} from "rxjs";
import {debounceTime} from "rxjs/operators";
import {Compartment, EditorState} from "@codemirror/state";
import {basicSetup, EditorView} from "@codemirror/basic-setup";
import {HighlightStyle, tags} from "@codemirror/highlight";
import {keymap} from "@codemirror/view";
import {selectAll} from "@codemirror/commands";
import {sql} from "@codemirror/lang-sql";
import {MoveSingleSql} from "../service/dto/move-single-sql";
import {ErrorModalComponent} from "../../../../../services/http/error-modal/error-modal.component";
import {NzModalService} from "ng-zorro-antd/modal";

@Component({
  selector: 'app-sql-management',
  templateUrl: './sql-management.component.html',
  styleUrls: ['./sql-management.component.less']
})
export class SqlManagementComponent implements OnInit, OnDestroy {

  validateForm = new FormGroup({
    schemaName: new FormControl(''),
    productId: new FormControl(''),
  })

  @ViewChild('editor', {static: false})
  holder
  view: EditorView

  allProducts: BarnProduct[]

  sqlList: BarnSql[]
  total = 0;
  current = 1;
  pageSize = 20;
  loading = false;
  pageSizes = [this.pageSize, 50, 100]

  selected: BarnSql
  _targetId: string
  target$ = new Subject<string>();
  targetObservable = this.target$.asObservable().pipe(debounceTime(500))
  targetSubscription: Subscription
  isVisible = false
  targetSql: BarnSql

  constructor(private productService: ProductService, private sqlService: BarnSqlService, private clipboard: Clipboard,
              private msg: NzMessageService, private modal: NzModalService) {
  }

  ngOnDestroy(): void {
    this.targetSubscription.unsubscribe()
  }

  ngOnInit(): void {
    const param = new BarnProduct();
    param.enable = Constants.Enable.YES
    this.productService.query(param).subscribe(value => {
      this.allProducts = value.data
    })
    this.targetSubscription = this.targetObservable.subscribe(value => {
      if (!value || !value.trim()) {
        this.targetSql = null
        return
      }
      this.sqlService.getById(value).subscribe(sql => {
        this.targetSql = sql
        if (this.targetSql && this.targetSql.sqlText) {
          setTimeout(() => {
            this.initSqlEditor()
            const t = this.view.state.update({changes: {insert: sql.sqlText, from: 0}});
            this.view.dispatch(t);
          }, 50);
        }
      });
    })
  }

  search() {
    const productId = this.validateForm.get("productId").value;
    if (!productId) {
      this.msg.error("请选择产品！");
      return
    }
    this.loading = true;
    const param = this.validateForm.getRawValue();
    this.sqlService.query(param, this.current, this.pageSize).subscribe(value => {
      this.sqlList = value.data
      this.current = value.current || 1
      this.total = value.count || 1
      this.loading = false
    }, () => this.loading = false)
  }

  resetForm() {
    this.validateForm.reset({productId: ''})
  }

  moveOneSql(selected: BarnSql) {
    this.isVisible = true
    this.selected = selected
  }

  set targetId(id: string) {
    this.target$.next(id)
  }

  get targetId() {
    return this._targetId
  }

  copyId(pid: string) {
    const result = this.clipboard.copy(pid);
    if (result) {
      this.msg.success(`复制${pid}成功`)
    } else {
      this.msg.error('复制失败')
    }
  }

  dialogCancel() {
    this.isVisible = false
    this.targetSql = null
    this.selected = null
  }

  // 确认移动
  confirmMove() {
    const param = new MoveSingleSql()
    param.from = this.selected.pid;
    param.to = this.targetSql.pid;
    this.sqlService.moveOneSql(param, false).subscribe(() => {
      this.msg.success("操作成功")
      this.search()
    }, (error => {

      if (error.error?.status === 'MOVE_SQL_BUSY') {
        this.msg.error(`${error.error?.data.userName}(${error.error?.data.userAccount})正在操作，请稍后！`)
      } else if (error.error?.status === "PRODUCT_NOT_SAME" || error.error?.status === "DATA_INCOMPLETE") {
        this.msg.error(`操作失败：${error.error?.message}`)
      } else {
        this.modal.create({
          nzTitle: '请求出错',
          nzContent: ErrorModalComponent,
          nzFooter: null,
          nzComponentParams: {
            url: error.url,
            status: error.status,
            errorMessage: error.message,
            code: error.error?.status,
            detail: error.error?.message + "\n" + error.error?.exception
          },
        });
      }
      console.log(error)
    }), () => {
      this.dialogCancel()
    })
  }


  /**
   * 初始化编辑器
   */
  initSqlEditor() {
    const language = new Compartment()
    const tabSize = new Compartment()

    // 设置编辑器样式
    const myTheme = EditorView.theme({
      '&': {
        backgroundColor: '#fff'
      },
      '&.cm-editor': {
        height: '200px',
        width: '600px'
      }
    }, {dark: false})

    // 设置高亮样式
    const myHighlightStyle = HighlightStyle.define([
      {tag: tags.keyword, color: '#f1a703', fontWeight: 'border'},
      {tag: tags.quote, color: '#f1a703', fontWeight: 'border'},
      {tag: tags.comment, color: '#f5d', fontStyle: 'italic'}
    ])

    // 设置编辑器的基本属性
    const state = EditorState.create({
      extensions: [
        basicSetup,
        keymap.of([{key: "Ctrl-a", run: selectAll}]),
        language.of(sql()),
        EditorView.editable.of(false),
        tabSize.of(EditorState.tabSize.of(4)),
        myTheme,
        myHighlightStyle
      ]
    })

    // 初始化
    this.view = new EditorView({
      state,
      parent: this.holder.nativeElement
    })

  }
}
